package com.stm.bi.repository.report;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stm.bi.dto.cmd.SubjectAdd;
import com.stm.bi.dto.cmd.SubjectUpd;
import com.stm.bi.dto.query.SubjectListQry;
import com.stm.bi.dto.query.SubjectPageQry;
import com.stm.bi.dto.vo.SubjectVO;
import com.stm.bi.repository.report.dataobject.SubjectCategoryDO;
import com.stm.bi.repository.report.dataobject.SubjectDO;
import com.stm.bi.repository.report.mapper.SubjectMapper;
import com.stm.framework.core.tookit.BeanToolkit;
import com.stm.framework.core.util.StringUtil;
import com.stm.framework.model.CustomizePage;
import com.stm.framework.repository.BaseRepository;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 科目-仓储
 *
 * @author qinyongjie
 * @date 2025-05-22
 */
@Repository
public class SubjectRepository extends BaseRepository<SubjectMapper, SubjectDO, SubjectVO> {

    @Resource
    private SubjectCategoryRepository subjectCategoryRepository;

    /**
     * 创建科目
     */
    public boolean create(SubjectAdd subjectAdd) {
        // 转换为DO对象
        SubjectDO subjectDO = BeanToolkit.instance().copy(subjectAdd, SubjectDO.class);

        // 处理subjectParam转换
        String subjectParamStr = convertSubjectParamToString(subjectAdd.getSubjectParam());
        subjectDO.setSubjectParam(subjectParamStr);

        // 生成科目ID
        String subjectCode = generateSubjectCode(subjectDO.getCategoryId());
        subjectDO.setSubjectCode(subjectCode);

        return this.save(subjectDO);
    }

    /**
     * 更新科目
     */
    public boolean update(SubjectUpd subjectUpd) {
        // 转换为DO对象
        SubjectDO subjectDO = BeanToolkit.instance().copy(subjectUpd, SubjectDO.class);

        // 处理subjectParam转换
        String subjectParamStr = convertSubjectParamToString(subjectUpd.getSubjectParam());
        subjectDO.setSubjectParam(subjectParamStr);

        // 检查categoryId是否改动，如果改动则重新生成subjectCode
        //checkAndRegenerateSubjectCode(subjectDO);

        return this.update(subjectDO);
    }

    /**
     * 科目分页查询
     *
     * @param subjectPageQry 科目查询入参对象
     * @return
     */
    public CustomizePage<SubjectVO> selectPage(SubjectPageQry subjectPageQry) {
        LambdaQueryWrapper<SubjectDO> queryWrapper = buildQueryListWrapper(subjectPageQry);
        IPage<SubjectDO> page = new Page(subjectPageQry.getPageNum(), subjectPageQry.getPageSize());
        page = this.baseMapper.selectPage(page, queryWrapper);
        // 使用Stream API进行转换
        List<SubjectVO> voList = page.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        CustomizePage<SubjectVO> customizePage = new CustomizePage<>(voList, page.getSize(), page.getCurrent(), page.getTotal());
        return customizePage;
    }

    /**
     * 科目列表查询
     *
     * @param subjectListQry 科目查询入参对象
     * @return
     */
    public List<SubjectVO> selectList(SubjectListQry subjectListQry) {
        LambdaQueryWrapper<SubjectDO> queryWrapper = buildeQueryWrapper(subjectListQry);
        List<SubjectDO> records = this.baseMapper.selectList(queryWrapper);

        // 使用Stream API进行转换
        return records.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 根据ID查询单个科目
     *
     * @param id 科目ID
     * @return 科目VO对象
     */
    public SubjectVO selectById(Long id) {
        SubjectDO subjectDO = this.getById(id);
        if (subjectDO == null) {
            return null;
        }
        return convertToVO(subjectDO);
    }

    /**
     * 检查categoryId是否改动，如果改动则重新生成subjectCode
     *
     * @param subjectDO 待更新的科目对象
     */
    private void checkAndRegenerateSubjectCode(SubjectDO subjectDO) {
        // 查询原有数据
        SubjectDO originalSubject = this.getById(subjectDO.getId());
        if (originalSubject == null) {
            throw new RuntimeException("科目不存在，无法更新，id: " + subjectDO.getId());
        }

        // 比较categoryId是否发生改动
        if (!subjectDO.getCategoryId().equals(originalSubject.getCategoryId())) {
            // categoryId发生改动，重新生成subjectCode
            String newSubjectCode = generateSubjectCode(subjectDO.getCategoryId());
            subjectDO.setSubjectCode(newSubjectCode);
        }
    }

    /**
     * 处理科目参数转换：将List<String>转换为分号分隔的字符串
     *
     * @param subjectParam 科目参数列表
     * @return 分号分隔的字符串，如果列表为空则返回null
     */
    private String convertSubjectParamToString(List<String> subjectParam) {
        if (subjectParam != null && !subjectParam.isEmpty()) {
            return String.join(";", subjectParam);
        }
        return null;
    }

    /**
     * 生成科目ID
     * 生成规则：科目归属的业务属性（例：MK/MD/MG）+年份月份4位数（例：2505）+随机5位数字(0-9随机，可重复)
     *
     * @param categoryId 科目分类ID
     * @return 生成的科目ID
     */
    private String generateSubjectCode(Long categoryId) {
        try {
            // 1. 通过categoryId查询分类信息
            SubjectCategoryDO category = subjectCategoryRepository.getById(categoryId);
            if (category == null) {
                throw new RuntimeException("科目分类不存在，categoryId: " + categoryId);
            }

            // 2. 解析path，找到顶级业务属性ID
            String path = category.getPath();
            if (StringUtil.isEmpty(path)) {
                throw new RuntimeException("科目分类路径为空，categoryId: " + categoryId);
            }

            // path格式: "0,7159678438715648,7159678438727936"
            String[] pathIds = path.split(",");
            
            Long topCategoryId;
            SubjectCategoryDO topCategory;
            
            if (pathIds.length == 1) {  
                // 直接在顶级分类下建科目，使用当前分类作为业务属性
                topCategoryId = categoryId;
                topCategory = category;
            } else {
                // 在二级及以下分类建科目，获取第二级ID（跳过0级根目录）
                topCategoryId = Long.parseLong(pathIds[1].trim());
                // 3. 查询顶级业务属性
                topCategory = subjectCategoryRepository.getById(topCategoryId);
                if (topCategory == null) {
                    throw new RuntimeException("顶级业务属性不存在，topCategoryId: " + topCategoryId);
                }
            }

            String businessAttribute = topCategory.getName();
            if (StringUtil.isEmpty(businessAttribute)) {
                throw new RuntimeException("业务属性名称为空，topCategoryId: " + topCategoryId);
            }

            // 4. 生成年份月份（YYMM格式）
            LocalDateTime now = LocalDateTime.now();
            String yearMonth = now.format(DateTimeFormatter.ofPattern("yyMM"));

            // 5. 生成5位随机数字
            Random random = new Random();
            int randomNum = random.nextInt(100000); // 0-99999
            String randomStr = String.format("%05d", randomNum); // 补零到5位

            // 6. 拼接生成科目ID
            return businessAttribute + yearMonth + randomStr;

        } catch (Exception e) {
            throw new RuntimeException("生成科目ID失败：" + e.getMessage(), e);
        }
    }

    /**
     * 将SubjectDO转换为SubjectVO
     *
     * @param subjectDO 数据对象
     * @return 视图对象
     */
    private SubjectVO convertToVO(SubjectDO subjectDO) {
        // 特殊处理subjectParam字段：String -> List<String>
        List<String> subjectParam = convertStringToSubjectParam(subjectDO.getSubjectParam());
        subjectDO.setSubjectParam(null);

        // 使用BeanToolkit进行基础字段映射（会忽略类型不匹配的字段）
        SubjectVO vo = BeanToolkit.instance().copy(subjectDO, SubjectVO.class);
        vo.setSubjectParam(subjectParam);
        return vo;
    }

    /**
     * 处理科目参数转换：将分号分隔的字符串转换为List<String>
     *
     * @param subjectParamStr 分号分隔的字符串
     * @return 科目参数列表，如果字符串为空则返回null
     */
    private List<String> convertStringToSubjectParam(String subjectParamStr) {
        if (StringUtil.isNotEmpty(subjectParamStr)) {
            return List.of(subjectParamStr.split(";"));
        }
        return null;
    }

    /**
     * 根据分类ID列表统计科目数量
     *
     * @param categoryIds 分类ID列表
     * @return 分类ID与科目数量的映射
     */
    public Map<Long, Long> countByCategoryIds(List<Long> categoryIds) {
        if (CollectionUtils.isEmpty(categoryIds)) {
            return new HashMap<>();
        }

        LambdaQueryWrapper<SubjectDO> queryWrapper = Wrappers.<SubjectDO>lambdaQuery()
                .in(SubjectDO::getCategoryId, categoryIds)
                .select(SubjectDO::getCategoryId);

        List<SubjectDO> subjects = this.baseMapper.selectList(queryWrapper);

        return subjects.stream()
                .collect(Collectors.groupingBy(
                        SubjectDO::getCategoryId,
                        Collectors.counting()
                ));
    }

    private LambdaQueryWrapper buildeQueryWrapper(SubjectListQry subjectListQry) {
        LambdaQueryWrapper<SubjectDO> queryWrapper = Wrappers.<SubjectDO>lambdaQuery()
                .eq(StringUtil.isNotEmpty(subjectListQry.getId()), SubjectDO::getId, subjectListQry.getId())
                .eq(StringUtil.isNotEmpty(subjectListQry.getOrgId()), SubjectDO::getOrgId, subjectListQry.getOrgId())
                .eq(StringUtil.isNotEmpty(subjectListQry.getName()), SubjectDO::getName, subjectListQry.getName())
                .eq(StringUtil.isNotEmpty(subjectListQry.getSubjectCode()), SubjectDO::getSubjectCode, subjectListQry.getSubjectCode())
                .eq(StringUtil.isNotEmpty(subjectListQry.getCategoryId()), SubjectDO::getCategoryId, subjectListQry.getCategoryId())
                .eq(StringUtil.isNotEmpty(subjectListQry.getParamType()), SubjectDO::getParamType, subjectListQry.getParamType())
                .eq(StringUtil.isNotEmpty(subjectListQry.getSubjectParam()), SubjectDO::getSubjectParam, subjectListQry.getSubjectParam())
                .eq(StringUtil.isNotEmpty(subjectListQry.getDefinition()), SubjectDO::getDefinition, subjectListQry.getDefinition())
                .eq(StringUtil.isNotEmpty(subjectListQry.getFieldName()), SubjectDO::getFieldName, subjectListQry.getFieldName())
                .eq(StringUtil.isNotEmpty(subjectListQry.getUnit()), SubjectDO::getUnit, subjectListQry.getUnit())
                .eq(StringUtil.isNotEmpty(subjectListQry.getRandomRange()), SubjectDO::getRandomRange, subjectListQry.getRandomRange())
                .eq(StringUtil.isNotEmpty(subjectListQry.getStatus()), SubjectDO::getStatus, subjectListQry.getStatus())
                .eq(StringUtil.isNotEmpty(subjectListQry.getCreator()), SubjectDO::getCreator, subjectListQry.getCreator())
                .eq(StringUtil.isNotEmpty(subjectListQry.getCreatorId()), SubjectDO::getCreatorId, subjectListQry.getCreatorId())
                .eq(StringUtil.isNotEmpty(subjectListQry.getCreateDt()), SubjectDO::getCreateDt, subjectListQry.getCreateDt())
                .eq(StringUtil.isNotEmpty(subjectListQry.getLastUpdater()), SubjectDO::getLastUpdater, subjectListQry.getLastUpdater())
                .eq(StringUtil.isNotEmpty(subjectListQry.getLastUpdaterId()), SubjectDO::getLastUpdaterId, subjectListQry.getLastUpdaterId())
                .eq(StringUtil.isNotEmpty(subjectListQry.getLastUpdateDt()), SubjectDO::getLastUpdateDt, subjectListQry.getLastUpdateDt())
                .eq(StringUtil.isNotEmpty(subjectListQry.getDeleted()), SubjectDO::getDeleted, subjectListQry.getDeleted())
                .eq(StringUtil.isNotEmpty(subjectListQry.getRemark()), SubjectDO::getRemark, subjectListQry.getRemark());
        return queryWrapper;
    }

    private LambdaQueryWrapper buildQueryListWrapper(SubjectPageQry subjectPageQry) {
        LambdaQueryWrapper<SubjectDO> queryWrapper = Wrappers.<SubjectDO>lambdaQuery()
                .like(StringUtil.isNotEmpty(subjectPageQry.getName()), SubjectDO::getName, subjectPageQry.getName());
        
        // 处理categoryId：支持递归查询子分类
        if (StringUtil.isNotEmpty(subjectPageQry.getCategoryId())) {
            // 获取当前分类及其所有子分类的ID列表
            List<Long> allCategoryIds = subjectCategoryRepository.selectAllSubCategoryIds(subjectPageQry.getCategoryId());
            if (!CollectionUtils.isEmpty(allCategoryIds)) {
                queryWrapper.in(SubjectDO::getCategoryId, allCategoryIds);
            } else {
                // 如果没有找到任何分类ID，则使用原始的categoryId进行精确匹配
                queryWrapper.eq(SubjectDO::getCategoryId, subjectPageQry.getCategoryId());
            }
        }
        
        // 按创建时间升序排序
        queryWrapper.orderByAsc(SubjectDO::getCreateDt);
        
        return queryWrapper;
    }

    /**
     * 根据科目名称模糊查询科目列表
     *
     * @param subjectName 科目名称
     * @return 科目列表
     */
    public List<SubjectVO> selectBySubjectName(String subjectName) {
        if (StringUtil.isEmpty(subjectName)) {
            return new ArrayList<>();
        }
        
        LambdaQueryWrapper<SubjectDO> queryWrapper = Wrappers.<SubjectDO>lambdaQuery()
                .like(SubjectDO::getName, subjectName)
                .orderByAsc(SubjectDO::getCreateDt);
        
        List<SubjectDO> records = this.baseMapper.selectList(queryWrapper);
        
        return records.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }
}
